package com.mxq.eclipse.mqtt.demo.subscribe;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * 订阅客户端连接
 * @author xiaoqiang
 * @date 2020-05-09 16:10
 */
@Slf4j
@Data
@Component
public class SubscribeConnect {
    @Value("${mqtt.broker}")
    private String broker;

    private MqttClient mqttClient;
    private MqttConnectOptions mqttConnectOptions;

    /**
     * 连接emq服务器
     */
    public MqttClient getConn(MqttSubscribeDto subscribeDto) {
        try {
            // host为主机名，clientId即连接MQTT的客户端ID，一般以客户端唯一标识符表示，MemoryPersistence设置clientId的保存形式，默认为以内存保存
            mqttClient = new MqttClient(broker, UUID.randomUUID().toString(), new MemoryPersistence());
            // MQTT的连接设置
            mqttConnectOptions = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
            mqttConnectOptions.setCleanSession(true);
            // 设置连接的用户名
            mqttConnectOptions.setUserName(subscribeDto.getUserName());
            // 设置连接的密码
            mqttConnectOptions.setPassword(subscribeDto.getPassword().toCharArray());
            // 设置超时时间 单位为秒
            mqttConnectOptions.setConnectionTimeout(10);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*keepAliveInterval秒的时间向客户端发送个消息判断客户端是否在线，
            // 但这个方法并没有重连的机制
            mqttConnectOptions.setKeepAliveInterval(5);
            // mqttConnectOptions.setServerURIs(); 配置多个服务器列表，一个挂掉会自动切换到其他正常的服务器，挂掉的服务器正常后，客户端会再次切换回来
            mqttClient.setCallback(new SubscribeCallback(subscribeDto));
            IMqttToken iMqttToken = mqttClient.connectWithResult(mqttConnectOptions);
            log.info("连接服务器成功，IMqttToken:{}",iMqttToken);

        } catch (MqttException e) {
            log.info("订阅连接MQTT服务器失败，失败原因：{}", e.getMessage());
        }
        return mqttClient;
    }
}
